package com.huike.report.service.impl;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

import com.huike.business.domain.vo.BusinessChangeVO;
import com.huike.business.mapper.BusinessMapper;
import com.huike.clues.domain.TbAssignRecord;
import com.huike.clues.domain.vo.ClueChangeVO;
import com.huike.clues.mapper.ClueMapper;
import com.huike.common.core.domain.entity.SysDictData;
import com.huike.report.domain.vo.IndexVo;
import com.google.errorprone.annotations.Var;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.huike.business.domain.TbBusiness;
import com.huike.business.mapper.TbBusinessMapper;
import com.huike.clues.domain.TbActivity;
import com.huike.clues.domain.TbClue;
import com.huike.clues.domain.TbCourse;
import com.huike.clues.domain.vo.ClueReportVo;
import com.huike.clues.mapper.*;
import com.huike.common.core.domain.AjaxResult;
import com.huike.common.core.page.TableDataInfo;
import com.huike.report.domain.ChannelStatistics;
import com.huike.report.domain.DeptStatistics;
import com.huike.report.domain.OwnerShipStatstics;
import com.huike.report.domain.dto.ContractStatisticsDTO;
import com.huike.report.domain.dto.StatisticsPageDTO;
import com.huike.report.domain.vo.*;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Service;

import com.huike.contract.domain.TbContract;
import com.huike.contract.mapper.TbContractMapper;
import com.huike.report.mapper.ReportMapper;
import com.huike.report.service.IReportService;

@Service
public class ReportServiceImpl implements IReportService {

    @Autowired
    private BusinessMapper businessMapper;

    @Autowired
    private ClueMapper clueMapper;


    @Autowired
    private ReportMapper reportMapper;

    @Autowired
    private TbContractMapper contractMapper;

    @Autowired
    private TbCourseMapper courseMapper;
    @Autowired
    private TbClueMapper tbclueMapper;

    @Autowired
    private TbBusinessMapper tbbusinessMapper;

    @Autowired
    private SysDeptMapper deptMapper;

    @Autowired
    private SysDictDataMapper dictDataMapper;


    /**
     * *************看我看我**************
     * 传入两个时间范围，返回这两个时间范围内的所有时间，并保存在一个集合中
     *
     * @param beginTime
     * @param endTime
     * @return
     * @throws ParseException
     */
    public static List<String> findDates(String beginTime, String endTime)
            throws ParseException {
        List<String> allDate = new ArrayList();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        Date dBegin = sdf.parse(beginTime);
        Date dEnd = sdf.parse(endTime);
        allDate.add(sdf.format(dBegin));
        Calendar calBegin = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calBegin.setTime(dBegin);
        Calendar calEnd = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calEnd.setTime(dEnd);
        // 测试此日期是否在指定日期之后
        while (dEnd.after(calBegin.getTime())) {
            // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
            calBegin.add(Calendar.DAY_OF_MONTH, 1);
            allDate.add(sdf.format(calBegin.getTime()));
        }
        System.out.println("时间==" + allDate);
        return allDate;
    }



    /**
     * ************看我看我***********
     * 用我能少走很多路
     * 我是用来机选百分比的方法
     *
     * @param all
     * @param num
     * @return
     */
    private BigDecimal getRadio(Integer all, Long num) {
        if (all.intValue() == 0) {
            return new BigDecimal(0);
        }
        BigDecimal numBigDecimal = new BigDecimal(num);
        BigDecimal allBigDecimal = new BigDecimal(all);
        BigDecimal divide = numBigDecimal.divide(allBigDecimal, 4, BigDecimal.ROUND_HALF_UP);
        return divide.multiply(new BigDecimal(100));
    }


    @Override
    public VulnerabilityMapVo getVulnerabilityMap(String beginCreateTime, String endCreateTime) {
        VulnerabilityMapVo vulnerabilityMapVo = new VulnerabilityMapVo();
        //线索总数
        int cluesNums = tbclueMapper.getCluesNums(beginCreateTime, endCreateTime);

        //有效线索数
        int effectiveCluesNums = tbclueMapper.getEffectiveCluesNums(beginCreateTime, endCreateTime);

        //商机数
        int businessNums = tbbusinessMapper.getBusinessNums(beginCreateTime, endCreateTime);

        //合同数
        int contractNums = contractMapper.getContractNums(beginCreateTime, endCreateTime);


        vulnerabilityMapVo.setCluesNums(cluesNums);
        vulnerabilityMapVo.setEffectiveCluesNums(effectiveCluesNums);
        vulnerabilityMapVo.setBusinessNums(businessNums);
        vulnerabilityMapVo.setContractNums(contractNums);
        return vulnerabilityMapVo;
    }




    private List<String> selectOfDate(LocalDate begin, LocalDate end, Function function){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        List<String> dates = null;
        try {
            dates = findDates(begin.toString(), end.toString());

            for (String date : dates) {
                function.apply(sdf.parse(date));
            }

        }catch (Exception e){
            e.printStackTrace();
        }
        return dates;
    }

    private interface Function{
        void apply(Date date);
    }

    @Override
    public List<ChannelStatisticsVO> chanelStatistics(LocalDate beginTime, LocalDate endTime) {
        LocalDateTime begin = LocalDateTime.of(beginTime,LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(endTime,LocalTime.MAX);
        List<ChannelStatisticsVO> getchannel = reportMapper.getchannel(begin, end);
        return getchannel;
    }

    @Override
    public TableDataInfo activityStatisticsList(Integer pageNum, Integer pageSize, LocalDate beginCreateTime, LocalDate endCreateTime, String name, String code, Integer total) {

        LocalDateTime begin = LocalDateTime.of(beginCreateTime,LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(endCreateTime,LocalTime.MAX);

        PageHelper.startPage(pageNum,pageSize);
        Page<ActivityStatisticsVo> page = (Page<ActivityStatisticsVo>) reportMapper.getactivityvos(begin,end,name,code);
        for (ActivityStatisticsVo activityStatisticsVo : page) {
            Long tbactivityCode = reportMapper.getTbactivityCode(activityStatisticsVo.getCode());
            Integer cluesNum = reportMapper.cluesNum(tbactivityCode);
            Integer falseCluesNum = reportMapper.getCluesNum(tbactivityCode, 4);
            Integer businessNum = reportMapper.getCluesNum(tbactivityCode, 6);
            Integer customersNum = reportMapper.getCluesNum(tbactivityCode, 7);
            activityStatisticsVo.setCluesNum(cluesNum);
            activityStatisticsVo.setFalseCluesNum(falseCluesNum);
            activityStatisticsVo.setBusinessNum(businessNum);
            activityStatisticsVo.setCustomersNum(customersNum);
            Integer amount = reportMapper.amount(tbactivityCode);
            Integer cost = reportMapper.cost(tbactivityCode);
            if (amount != null){
                activityStatisticsVo.setAmount(amount.doubleValue());
            }
            if (cost != null){
                activityStatisticsVo.setCost(cost.doubleValue());
            }

        }

        TableDataInfo tableDataInfo = new TableDataInfo();
        tableDataInfo.setTotal(page.getTotal());
        tableDataInfo.setRows(page.getResult());
        tableDataInfo.setMsg("查询成功");
        tableDataInfo.setCode(200);

        return tableDataInfo;
    }

    @Override
    public List<ActivityStatistics> activityStatistics(LocalDate beginTime, LocalDate endTime) {

        LocalDateTime begin = LocalDateTime.of(beginTime,LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(endTime,LocalTime.MAX);
        List<ActivityStatistics> getactivity = reportMapper.getactivity(begin, end);

        return getactivity;
    }

    @Override
    public TableDataInfo cluesStatisticsList(Integer pageNum, Integer pageSize, LocalDate beginCreateTime, LocalDate endCreateTime, Long id, String owner) {

        PageHelper.startPage(pageNum,pageSize);

        LocalDateTime begin = LocalDateTime.of(beginCreateTime,LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(endCreateTime,LocalTime.MAX);

        Page<ClueReportVo> page = (Page<ClueReportVo>) reportMapper.getClueReportPages(begin,end,id,owner);
            for (ClueReportVo tbClue : page) {
                TbBusiness tbBusiness = reportMapper.gettbBusinessByClueId(tbClue.getId());
                if (tbClue.getActivityId() != null){
                    TbActivity tbActivity = reportMapper.gettbActivityByClueId(tbClue.getActivityId());
                    if (tbActivity != null){
                        tbClue.setCode(tbActivity.getCode());
                        tbClue.setInfo(tbActivity.getInfo());

                    }
                }
                if(tbBusiness != null){
                    tbClue.setBusinessStatus(tbBusiness.getStatus());
                    tbClue.setBusinessCreateTime(tbBusiness.getCreateTime());
                    TbContract tbContract = reportMapper.gettbContractByBusinessId(tbBusiness.getId());
                    if (tbContract != null){
                        tbClue.setContractCreateTime(tbContract.getCreateTime());
                        tbClue.setOrder(Double.parseDouble(String.valueOf(tbContract.getOrder())));
                    }
                }

                TbAssignRecord tbAssignRecordByClueId = reportMapper.getTbAssignRecordByClueId(tbClue.getId(),tbClue.getCreate_by());
                if (tbAssignRecordByClueId != null){
                    tbClue.setOwner(tbAssignRecordByClueId.getUserName());
                    tbClue.setDeptId(tbAssignRecordByClueId.getDeptId().toString());
                    tbClue.setDeptName(reportMapper.getDeptName(tbAssignRecordByClueId.getDeptId()));
                }

            }

            TableDataInfo tableDataInfo = new TableDataInfo();
            tableDataInfo.setTotal(page.getTotal());
            tableDataInfo.setRows(page.getResult());
            tableDataInfo.setMsg("查询成功");
            tableDataInfo.setCode(200);
            return tableDataInfo;
    }

    @Override
    public LineChartVO cluesStatistics(LocalDate begin, LocalDate end) {

        try{
            LineChartVO lineChartVO = new LineChartVO();
            List<String> dates = findDates(begin.toString(), end.toString());
            List<LocalDate> localDates = new ArrayList<>();

            localDates.add(begin);
            while (!begin.equals(end)){
                begin = begin.plusDays(1);
                localDates.add(begin);
            }
            List<Object> newuser = new ArrayList<>();
            List<Object> countusser = new ArrayList<>();
            for (LocalDate localDate : localDates) {

                LocalDateTime beginTime = LocalDateTime.of(localDate, LocalTime.MIN);
                LocalDateTime endTime = LocalDateTime.of(localDate,LocalTime.MAX);

                Integer NewuserCount = reportMapper.getUserCount(beginTime, endTime);
                Integer TotalUserCount = reportMapper.getUserCount(null,endTime);
                newuser.add(NewuserCount);
                countusser.add(TotalUserCount);
            }

            List<LineSeriesVO> lineSeriesVOS = new ArrayList<>();
            LineSeriesVO lineSeriesVO = new LineSeriesVO();
            lineSeriesVO.setName("新增用户数量");
            lineSeriesVO.setData(newuser);
            lineSeriesVOS.add(lineSeriesVO);

            LineSeriesVO lineSeriesVO1 = new LineSeriesVO();
            lineSeriesVO1.setName("总用户数量");
            lineSeriesVO1.setData(countusser);
            lineSeriesVOS.add(lineSeriesVO1);

            lineChartVO.setxAxis(dates);
            lineChartVO.setSeries(lineSeriesVOS);

            return lineChartVO;
        }catch (Exception e){
            e.printStackTrace();
        }

        return null;
    }

    @Override
    public LineChartVO contractStatistics(LocalDate begin, LocalDate end) {


        LineChartVO lineChartVO = new LineChartVO();

        LineSeriesVO new_contract = new LineSeriesVO();
        new_contract.setName("新增客户数");

        LineSeriesVO all_contract = new LineSeriesVO();
        all_contract.setName("客户总数");

        List<Object> new_contract_list = new ArrayList<>();
        List<Object> all_contract_list = new ArrayList<>();
        List<String> dates = selectOfDate(begin,end,(date)-> {
            // 卡到当天
            Map<String,Object> map = new HashMap<>();
            map.put("endCreateTime",date);
            map.put("beginCreateTime",date);

            TbContract newContract = new TbContract();
            newContract.setParams(map);
            List<TbContract> newContracts = contractMapper.selectTbContractList(newContract);
            new_contract_list.add(newContracts!=null ? newContracts.size() : 0);


            map.clear();
            map.put("endCreateTime",date);
            TbContract allContract = new TbContract();
            allContract.setParams(map);
            List<TbContract> allContracts = contractMapper.selectTbContractList(allContract);
            all_contract_list.add(allContracts!=null?allContracts.size():0);
        });
        new_contract.setData(new_contract_list);
        all_contract.setData(all_contract_list);

        lineChartVO.setxAxis(dates);
        lineChartVO.setSeries(Arrays.asList(new_contract,all_contract));

        return lineChartVO;
    }

    @Override
    public TableDataInfo contractStatisticsList(ContractStatisticsDTO contractDTO) {
        PageHelper.startPage(contractDTO.getPageNum(),contractDTO.getPageSize());

        TbContract conditionContract = new TbContract();
        conditionContract.setChannel(contractDTO.getChannel()!=null ? String.valueOf(contractDTO.getChannel()) : null);
        conditionContract.setCreateBy(contractDTO.getCreateBy());
        conditionContract.setDeptId(contractDTO.getDeptId()!=null ? (long) contractDTO.getDeptId() : null);


        Map<String,Object> params = new HashMap<>();
        params.put("beginCreateTime",contractDTO.getBeginCreateTime());
        params.put("endCreateTime",contractDTO.getEndCreateTime());
        conditionContract.setParams(params);

        Page<TbContract> tbContracts = (Page<TbContract>)contractMapper.selectTbContractList(conditionContract);

        TableDataInfo tableDataInfo = new TableDataInfo(tbContracts.getResult(),(int)tbContracts.getTotal());
        tableDataInfo.setCode(200);
        return tableDataInfo;
    }

    @Override
    public List<SubjectStatisticsVO> subjectStatistics(LocalDate begin, LocalDate end) {

        return reportMapper.subjectStatistics(begin, end);
    }

    @Override
    public LineChartVO salesStatistics(LocalDate begin, LocalDate end) {

        LineChartVO lineChartVO = new LineChartVO();

        LineSeriesVO salesSeriesVo = new LineSeriesVO();

        List<Object> sales_series_list = new ArrayList<>();
        List<String> dates = selectOfDate(begin, end, (date) -> {
            Map<String,Object> map = new HashMap<>();
            map.put("endCreateTime",date);
            map.put("beginCreateTime",date);

            TbContract conditionContract = new TbContract();
            conditionContract.setParams(map);
            List<TbContract> tbContracts = contractMapper.selectTbContractList(conditionContract);

            Float price = 0.0F;
            for (TbContract tbContract : tbContracts) {
                price += tbContract.getOrder();
            }
            sales_series_list.add(price);

        });

        salesSeriesVo.setName("销售统计");
        salesSeriesVo.setData(sales_series_list);

        lineChartVO.setxAxis(dates);
        lineChartVO.setSeries(Arrays.asList(salesSeriesVo));

        return lineChartVO;
    }

    @Override
    public TableDataInfo deptStatisticsList(StatisticsPageDTO dto) {
        PageHelper.startPage(dto.getPageNum(),dto.getPageSize());

        Page<DeptStatistics> page = reportMapper.deptStatistics(dto);

        List<DeptStatisticsVO> vo_list = page.getResult().stream().map(deptStatistics -> {
            DeptStatisticsVO vo = DeptStatisticsVO.builder()
                    .total_amount(deptStatistics.getTotalAmount())
                    .deptName(deptStatistics.getDeptName())
                    .dept_id(deptStatistics.getDeptId())
                    .num(deptStatistics.getNum())
                    .build();
            return vo;
        }).collect(Collectors.toList());

        TableDataInfo tableDataInfo = new TableDataInfo(vo_list, (int)page.getTotal());
        tableDataInfo.setCode(200);
        return tableDataInfo;
    }

    @Override
    public TableDataInfo ownerShipStatisticsList(StatisticsPageDTO dto) {
        PageHelper.startPage(dto.getPageNum(),dto.getPageSize());
        Page<OwnerShipStatstics> page = reportMapper.ownerShipStatistics(dto);
        List<OwnerShipStatisticsVO> vo_list = page.getResult().stream().map(ownerShipStatstics -> OwnerShipStatisticsVO.builder()
                .create_by(ownerShipStatstics.getCreateBy())
                .total_amount(ownerShipStatstics.getTotalAmount())
                .num(ownerShipStatstics.getNum())
                .build()).collect(Collectors.toList());

        TableDataInfo tableDataInfo = new TableDataInfo(vo_list,(int)page.getTotal());
        tableDataInfo.setCode(200);
        return tableDataInfo;
    }

    @Override
    public TableDataInfo channelStatisticsList(StatisticsPageDTO dto) {
        PageHelper.startPage(dto.getPageNum(),dto.getPageSize());

        Page<ChannelStatistics> page = reportMapper.channelStatistics(dto);
        List<ChannelStatisticsVO> vo_list = page.getResult()
                .stream().map(channelStatistics -> ChannelStatisticsVO.builder()
                .channel(channelStatistics.getChannel())
                .total_amount(channelStatistics.getTotalAmount())
                .num(channelStatistics.getNum())
                .build()
        ).collect(Collectors.toList());

        TableDataInfo tableDataInfo = new TableDataInfo(vo_list,(int)page.getTotal());
        tableDataInfo.setCode(200);
        return tableDataInfo;
    }
    /**
     * 线索转化龙虎榜
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<ClueChangeVO> salesStatistic(LocalDate beginCreateTime, LocalDate endCreateTime,Integer deptId) {
        LocalDateTime beginTime = LocalDateTime.of(beginCreateTime, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(endCreateTime, LocalTime.MAX);
        //获取总线索数
        Integer clueAll = clueMapper.getCluesNums(beginTime,endTime);
        //获取线索转化数
        List<ClueChangeVO> list = clueMapper.getSalesStatistic(beginTime,endTime);
        List<ClueChangeVO> collect = list.stream().map(lt -> {
            lt.setRadio(getRadio(clueAll, lt.getNum()));
            lt.setCreate_by(lt.getCreateBy());
            return lt;
        }).collect(Collectors.toList());
        return collect;
    }


    /**
     * 商机龙虎榜
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<BusinessChangeVO> businessChangeStatistics(LocalDate beginCreateTime, LocalDate endCreateTime,Integer deptId) {

        LocalDateTime beginTime = LocalDateTime.of(beginCreateTime, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(endCreateTime, LocalTime.MAX);

        //获取商机总数
        Integer businessAll =businessMapper.getBusinessAll(beginTime,endTime);
        //获取转化商机数
        List<BusinessChangeVO> list = businessMapper.getbusinessChangeVOList(beginTime,endTime);
        List<BusinessChangeVO> collect = list.stream().map(lt -> {
            lt.setRadio(getRadio(businessAll, lt.getNum()));
            lt.setCreate_by(lt.getCreateBy());
            return lt;
        }).collect(Collectors.toList());
        return collect;
    }



//    @Override
//    public IndexVo getIndex(String beginCreateTime, String endCreateTime) {
//
//        return null;
//    }
}